/*
Copyright (C) 2010 Andrew Dieffenbach (www.puzzud.com).

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

package com.puzzud.engine.video;

import com.puzzud.engine.video.VideoObject;
import com.puzzud.engine.video.VideoImage;
import com.puzzud.engine.video.VideoSprite;

import com.puzzud.engine.video.VideoObject2D;
import com.puzzud.engine.utility.GameShell;

import java.awt.*;
import java.awt.image.*;
import java.awt.geom.*;
import java.awt.color.ColorSpace;
import java.util.Vector;

// VideoDisplay
public class VideoDisplay extends VideoObject2D
{
	Image backBufferImage;
	Graphics backBufferGraphics;
	int frameRate;

	private Color backgroundColor;
	private float[] backgroundColorWeight;

        private Color printColor;
	private float[] printColorWeight;
        private int printSize;

	int realWidth;
	int realHeight;

	AffineTransform affineTransform;

	GameShell gameShell;

	public VideoDisplay( GameShell gs )
	{
		super();

		gameShell = gs;

		gameShell.setDoubleBuffered( true );

		affineTransform = new AffineTransform();

		setRealDimensions( gs.getSize().width, gs.getSize().height );
		setDimensions( getRealWidth(), getRealHeight() );

		frameRate = 60;
		backgroundColorWeight = new float[] { 0.0f, 0.0f, 0.0f };
		setBackgroundColor( backgroundColorWeight );

                printColorWeight = new float[] { 1.0f, 1.0f, 1.0f, 1.0f };
		setPrintColor( printColorWeight );
                setPrintSize( 12 );
	}

	public VideoDisplay( int width, int height, GameShell gs )
	{
		super();

		gameShell = gs;

		gameShell.setDoubleBuffered( true );

		affineTransform = new AffineTransform();

		setRealDimensions( width, height );
                setDimensions( ( int )gameShell.getParent().getSize().getWidth(),
                                   ( int )gameShell.getParent().getSize().getHeight() );

		frameRate = 60;
		backgroundColorWeight = new float[] { 0.0f, 0.0f, 0.0f };
		setBackgroundColor( backgroundColorWeight );

                printColorWeight = new float[] { 1.0f, 1.0f, 1.0f, 1.0f };
		setPrintColor( printColorWeight );
                setPrintSize( 12 );
	}

	protected void setRealDimensions( int width, int height )
	{
		backBufferImage = gameShell.createImage( width, height );
		backBufferGraphics = backBufferImage.getGraphics();

		realWidth = width;
		realHeight = height;
	}

	public void setDimensions( int width, int height )
	{
		super.setDimensions( width, height );

                gameShell.setSize( width, height );

                affineTransform = new AffineTransform();
		affineTransform.translate( 0, 0 );
		affineTransform.scale( getXScale(), getYScale() );
	}

	public int getRealWidth()
	{
		return( realWidth );
	}

	public int getRealHeight()
	{
		return( realHeight );
	}

	public void draw( VideoImage tempVideoImage )
	{
            tempVideoImage.drawOnTo( this );
	}

        public void draw( VideoSprite tempVideoSprite )
	{
            tempVideoSprite.drawOnTo( this );
	}

	public void clear()
	{
		backBufferGraphics.setColor( backgroundColor );
		backBufferGraphics.fillRect( 0, 0, getRealWidth(), getRealHeight() );
	}

	public void display()
	{
		// Display backbuffer on this display.

		if( isScaled() )
		{
			//Graphics2D g2d = getBuffer();
			Graphics2D g2d = ( Graphics2D )gameShell.graphicsContext;

                        if( getScaleType() == VideoObject2D.SCALE_TYPE_EXACT )
                        {
                            g2d.setRenderingHint( RenderingHints.KEY_INTERPOLATION,
                                                 RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR );

                        }
                        else
                        {
                             g2d.setRenderingHint( RenderingHints.KEY_INTERPOLATION,
                                                   RenderingHints.VALUE_INTERPOLATION_BILINEAR  );
                        }

			//g2d.setTransform( affineTransform );    // NOTE: This state causes a flash sometimes when external object resizes it.
                        //gameShell.graphicsContext.drawImage( backBufferImage, 0, 0, gameShell );

                        gameShell.graphicsContext.drawImage( backBufferImage, 0, 0, this.width, this.height, gameShell );
		}
		else
		{
			gameShell.graphicsContext.drawImage( backBufferImage, 0, 0, null );
		}
	}

	public int getFrameRate()
	{
		return( frameRate );
	}

	public void setFrameRate( int frameRate )
	{
		this.frameRate = frameRate;
	}

	public float[] getBackgroundColor()
	{
		return( backgroundColorWeight );
	}

	public void setBackgroundColor( float[] color )
	{
		backgroundColorWeight[0] = color[0];
		backgroundColorWeight[1] = color[1];
		backgroundColorWeight[2] = color[2];

		//backgroundColor = null;
		backgroundColor = new Color( backgroundColorWeight[0], backgroundColorWeight[1], backgroundColorWeight[2] );
		//gameShell.setBackground( backgroundColor );	// This actually changes the widget's background color... wanted?
	}

	public Graphics2D getBuffer()
	{
		return( ( Graphics2D )backBufferGraphics );
	}

        public float[] getPrintColor()
	{
		return( printColorWeight );
	}

	public void setPrintColor( float[] color )
	{
		printColorWeight[0] = color[0];
		printColorWeight[1] = color[1];
		printColorWeight[2] = color[2];

                // Check if an alpha component was requested.
                if( color.length == 4 )
                {
                    printColorWeight[3] = color[3];
                    printColor = new Color( printColorWeight[0], printColorWeight[1], printColorWeight[2], printColorWeight[3] );
                }
                else
                {
                    printColor = new Color( printColorWeight[0], printColorWeight[1], printColorWeight[2] );
                }
	}

        public void setPrintSize( int size )
        {
            printSize = size;

            Font font = backBufferGraphics.getFont();

            font = new Font(font.getFamily(), font.getStyle(), printSize );

            backBufferGraphics.setFont( font );

            //Font font3 = new Font("Courier", Font.PLAIN,  18);


        }

	public void print( String line, int x, int y )
	{
            //backBufferGraphics.setFont( null );

            backBufferGraphics.setColor( printColor );
            backBufferGraphics.drawString( line, x, y );
	}

        public void drawRectangle( Point upperLeft, Point lowerRight )
        {
            backBufferGraphics.setColor( printColor );
            backBufferGraphics.fillRect( upperLeft.x, upperLeft.y, lowerRight.x - upperLeft.x, lowerRight.y - upperLeft.y );
            //backBufferGraphics.drawRe
        }

        public void drawRectangle( int upperLeftX, int upperLeftY, int lowerRightX, int lowerRightY )
        {
            backBufferGraphics.setColor( printColor );
            backBufferGraphics.fillRect( upperLeftX, upperLeftY, lowerRightX - upperLeftX, lowerRightY - upperLeftY );
        }

        public void drawArea( Area area )
        {
            backBufferGraphics.setColor( printColor );
            backBufferGraphics.setClip( area );
            backBufferGraphics.fillRect( 0 , 0 , getRealWidth(), getRealHeight() );
            backBufferGraphics.setClip( null );
        }

        public void drawAreaBounds( Area area )
        {
            backBufferGraphics.setColor( printColor );
            Rectangle bounds = area.getBounds();
            backBufferGraphics.fillRect( bounds.x, bounds.y, bounds.width + 1, bounds.height + 1 );
        }

        public void drawLine( Point origin, Point endpoint )
        {
            backBufferGraphics.setColor( printColor );
            backBufferGraphics.drawLine( origin.x, origin.y, endpoint.x, endpoint.y );
        }

        public void drawLine( int originX, int originY, int endpointX, int endpointY )
        {
            backBufferGraphics.setColor( printColor );
            backBufferGraphics.drawLine( originX, originY, endpointX, endpointY );
        }
}